#include "lin.h"

#define LINRW_R 0	  // read data from master
#define LINRW_W LINRW // write data to master

LINdata xdata EOP;	  ///< EOP数据
uint8 xdata EOP_RStime = 10;
/* 设置DMA传输地址*/
#define LIN_SETADDR(ADDR)        \
	if (ReadBit(LIN_CR, DMASEL)) \
		DMA1_BA = ADDR;          \
	else                         \
		DMA0_BA = ADDR

/* select reading or writing, RW: LINRW_R or LINRW_W*/
#define LIN_SETRW(RW)          \
	if (RW == LINRW_R)         \
		ClrBit(LIN_CR, LINRW); \
	else if (RW == LINRW_W)    \
	SetBit(LIN_CR, LINRW)

/* acknowledge */
#define LIN_SETACK() SetBit(LIN_CSR, LINACK)

/* 数组名称：linbuf
 * 功    能：为每个ID号留有对应的数据存储空间
 * 参数说明：
 * 注意事项：
 */
uint8 xdata ucaLinBuff[9] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,0x0};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/* 函数名称：LIN_Init
 * 函数功能：LIN模块设置
 * 参数说明：
 * 注意事项：
 */
void LIN_Init(void)
{
	/*-------------------------------------------------------------------------------------------------
		DMA通道配置
		DMASEL=1:配置为DMA1	DMASEL=0:配置为DMA0  从 UART2 到 XRAM
	-------------------------------------------------------------------------------------------------*/
    DMA0_BA =0;                     //带有bootLoder先清0再赋值
    DMA0_CR0=0;                     //带有bootLoder先清0再赋值
    LIN_CR =0;                      //带有bootLoder先清0再赋值
	SetBit(DMA0_CR0, DMAEN | DMACFG2 | DMACFG1);
	ClrBit(LIN_CR, DMASEL);
	DMA0_BA =(uint16)ucaLinBuff; /* 使用dma0，spi使用dma1 */
	/*-------------------------------------------------------------------------------------------------
	LIN通道配置
	00:配置为TXD：P00 RXD：p01;    ！！！！！6816的demo连接的时P36,37 需要飞线
	10:配置为TXD：P10 RXD：p11;
	11:单线lin P11
	注意：6806的P10P11没有内部上拉，端口转移时，P10需配置外部上拉
	注意：6806的P10P11没有内部上拉，端口转移时，P10需配置外部上拉
	注意：6806的P10P11没有内部上拉，端口转移时，P10需配置外部上拉
	------------------------------------------------------------------------------------------------*/
	SetBit(LIN_CR, CHSEL1); /* 端口转移 */
	SetBit(LIN_CR, CHSEL0); /* 端口转移 */
    SetBit(P1_PU, P11HV_EN);  // P11 高压输入模式，保持使能
	ClrBit(LIN_CR, AUTOSIZE); /* 自动长度设定（ID[4][5]决定） */
	SetBit(LIN_CR, LINIE);	  /* 中断设置 */
	SetBit(LIN_CSR, LINEN);	  /* LIN模块使能 */
}

/* 函数名称：LIN_Schdule
 * 函数功能：读取ID并对对应ID号进行操作
 * 参数说明：
 * 注意事项：
 */

/*-------------------------------------------------------------------------------------------------
	Function Name :	void LIN_list(uint8 PID)
	Description   :	总线收发列表 ，对接收的数据设置长度和检验类型 。对发送的数据设置
	Input         :	要发送的字符串的地址
	Output		  :	无
-------------------------------------------------------------------------------------------------*/
uint8 LIN_ID1 = 0;
void LIN_list(void)
{
	uint8 i = 0;
	LIN_ID1 = LIN_ID;
	switch (LIN_ID1)
	{
	case 0x2A:
		LIN_SETSIZE(8);	  /* 接收数据长度 */
		CheckEnhanced;	  /* 设置为标准校验模式 */
		LIN_MODE_Receive; /* 接收数据模式 */
		LIN_ACK;		  /* 响应帧头 */
		break;
    /********************发送数据处理****************/
    case 0x2E:			/*发送数据ID=0X2E*/
        LIN_SETSIZE(8); /* 发送数据长度 */
        ucaLinBuff[0] = (EOP.ECF_EnableSt | (EOP.ECF_WorkingSt << 1) | (EOP.ECF_WorkingMode << 2) | (0x0f << 4));
        ucaLinBuff[1] = EOP.ECF_Speed;
        ucaLinBuff[2] = EOP.ECF_Voltage;
        ucaLinBuff[3] = (((EOP.ECF_Voltage & 0x1ff) >> 8) | ((EOP.ECF_Current & 0x03) << 6) | (0x1f << 1));
        ucaLinBuff[4] = ((EOP.ECF_Current & 0x3ff) >> 2);
        ucaLinBuff[5] = EOP.ECF_Power & 0xff;
        ucaLinBuff[6] = (((EOP.ECF_Power & 0x3ff) >> 8) | (0x3f << 2));
        ucaLinBuff[7] = (((EOP.ECF_OverCurrentError & 0x01) << 7) |
                         ((EOP.ECF_StallError & 0x01) << 6) |
                         ((EOP.ECF_HardwareError & 0x01) << 5) |
                         ((EOP.ECF_OverTempError & 0x01) << 4) |
                         ((EOP.ECF_OverVoltageError & 0x01) << 3) |
                         ((EOP.ECF_UnderVoltageError & 0x01) << 2) |
                         ((EOP.ECF_LinLostError & 0x01) << 1) |
                         ((EOP.ECF_FaultSt & 0x01) << 0));
        CheckEnhanced; /* 设置为标准校验模式 */
        LIN_MODE_Send; /* 发送数据 */
        LIN_ACK;	   /* 响应帧头 */
        break;
    case 0x18:
		LIN_SETSIZE(8); /* 发送数据长度 */
        ucaLinBuff[0]=0x11;/*测试用 */
        ucaLinBuff[1]=0x22;
        ucaLinBuff[2]=0x33;
        ucaLinBuff[3]=0xff;
        ucaLinBuff[4]=0xff;
        ucaLinBuff[5]=0xff;
        ucaLinBuff[6]=0xff;
		ucaLinBuff[7]=0xff;
		CheckEnhanced; /* 设置为标准校验模式 */
		LIN_MODE_Send; /* 发送数据 */
		LIN_ACK;	   /* 响应帧头 */
		break;
		
		/*****************************/
		/*********诊断数据************/
		/*****************************/
	case 0x3c:			  /* 接收诊断数据 */
		LIN_SETSIZE(8);	  /* 接收数据长度 */
        CheckEnhanced;
		LIN_MODE_Receive; /* 接收数据模式 */
		LIN_ACK;		  /* 响应帧头 */
		break;

	case 0x3d:
		LIN_SETSIZE(8); /* 发送数据长度 */
		for (i = 0; i < 8; i++)
		{
			ucaLinBuff[i] = i; /* 设置发送的数据 */
		}
		CheckClass;	   /* 设置为标准校验模式 */
		LIN_MODE_Send; /* 发送数据 */
		LIN_ACK;	   /* 响应帧头 */
		break;
        
	default:
		ClrBit(LIN_SR, LINDONE); /* 清除传输完成产生中断的标志位 */
        LIN_MODE_Receive;        /* 接收数据模式，接收数据不响应帧头，只做接收，不需要LIN_ACK */
		break;
	}
}

/*  -------------------------------------------------------------------------------------------------
	Function Name  : ReceiveSYS
	Description    : 总线接收数据处理
	Date           :
				   : [输入]
	------------------------------------------------------------------------------------------------- */
void ReceiveSYS(uint8 PID)
{
	switch (PID)
	{
    /********************接收数据处理****************/
	case 0x2A:								 /*接收数据ID=0X2A*/
		EOP.EnableReq_ECF = ucaLinBuff[0];	 // 使能信号，无使能，即使有转速请求也不工作
		EOP.SpeedReq_ECF = ucaLinBuff[1];	 // 请求转速
    
    /********************诊断接收数据处理****************/
	case 0x3c:
            if ((ucaLinBuff[0] == 0x21) && (ucaLinBuff[1] == 0x06) &&
			(ucaLinBuff[2] == 0xB0) && (ucaLinBuff[3] == 0xFF) &&
			(ucaLinBuff[4] == 0x7F) && (ucaLinBuff[5] == 0xFF) &&
			(ucaLinBuff[6] == 0xFF) && (ucaLinBuff[7] == 0x22))
		{
            sc_goToSleep();                                          //指令帧进入休眠
		}
		break;

	default:
		break;
	}
}

/**
	@brief        EOP_回复的lin数据准备 10ms更新一次
	@date         2022-07-14
*/
void EOP_TXLIN(void)
{
	uint8 i = 0;
	if (EOP_RStime == 0)
	{
		EOP_RStime = 10; // 10ms更新一次数据

		if (EOP.EnableReq_ECF == 0) // 使能位
		{
			EOP.ECF_EnableSt = 0;
		}
		else
		{
			EOP.ECF_EnableSt = 1;
		}

		/* 工作模式设置 */
		if (mcState != mcRun)
		{
			EOP.ECF_WorkingMode = 0; // 空闲
		}
		else if (mcFocCtrl.CtrlMode == 0)
		{
			EOP.ECF_WorkingMode = 1; // 开环
		}
		else if (mcFocCtrl.CtrlMode == 1)
		{
			EOP.ECF_WorkingMode = 2; // 闭环
		}
		else
		{
			EOP.ECF_WorkingMode = 0; // 空闲
		}

		if (mcState == mcReady)
		{
			EOP.ECF_WorkingSt = 0;
		}
		else if (mcState == mcRun)
		{
			EOP.ECF_WorkingSt = 1;
		}

		EOP.ECF_Speed = (uint8)(mcFocCtrl.SpeedFlt / S_Value(15.0));		  // 反馈转速 精度：15rpm*Inc
		EOP.ECF_Voltage = (uint8)((mcFocCtrl.mcDcbusFlt / UDC_Value(0.1)));	  // 母线电压 分辨率0.1V
		EOP.ECF_Current = (uint16)(mcFocCtrl.mcADCCurrentbus / I_Value(0.1)); // 母线电流 分辨率0.1A
		EOP.ECF_Power = (EOP.ECF_Voltage * EOP.ECF_Current) / 100;  

		// 缺相 相短故障
		if (mcFaultSource == FaultHardOVCurrent || mcFaultSource == FaultPhaseLost)
		{
            EOP.ECF_HardwareError = 1;
		}

		// 软件过流故障
		if (mcFaultSource == FaultSoftOVCurrent)
		{
            EOP.ECF_OverCurrentError = 1;
		}

		// 欠压故障
		if (mcFaultSource == FaultUnderVoltageDC)
		{
            EOP.ECF_UnderVoltageError = 1;
		}

		// 过压故障延时
		if (mcFaultSource == FaultOverVoltageDC)
		{
            EOP.ECF_OverVoltageError = 1;
		}
        // 堵转故障延时
		if (mcFaultSource == FaultStall)
		{
			EOP.ECF_StallError = 1;
		}

		// 过温故障延时
		if (mcFaultSource == FaultNtcOTErr || mcFaultSource == FaultTSD)
		{
            EOP.ECF_OverTempError = 1;
		}

		// 故障总使能位
		if (mcFaultSource ==FaultNoSource )
		{
           EOP.ECF_HardwareError = 0;
           EOP.ECF_OverCurrentError = 0;
           EOP.ECF_UnderVoltageError = 0;
           EOP.ECF_OverVoltageError = 0;
           EOP.ECF_StallError = 0;
           EOP.ECF_OverTempError = 0;
           EOP.ECF_FaultSt = 0;
		}
        else
        {
            EOP.ECF_FaultSt = 1;
            EOP.ECF_WorkingSt = 0;
            EOP.ECF_WorkingMode = 0;
        }
            
	}
}
/**
	@brief        EOP_接收数据
	@date         2022-07-14
*/
void EOP_RXLIN(void)
{
	// 有使能信号并且有目标转速值
	if (EOP.EnableReq_ECF == 1)
	{
		if (EOP.SpeedReq_ECF <= 20) // 0-20 停止
		{
			isCtrlPowOn = false;
			mcFocCtrl.Ref = 0;
		}
		else if (EOP.SpeedReq_ECF <= 44) // 21-44 660rpm
		{
			isCtrlPowOn = true;
			mcFocCtrl.Ref = MOTOR_SPEED_MIN_RPM;
		}
		else if (EOP.SpeedReq_ECF <= 180) // 精度：15rpm*Inc  转速换算
		{
			isCtrlPowOn = true;
			mcFocCtrl.Ref = S_Value(EOP.SpeedReq_ECF * 15); // 精度：15rpm*Inc  转速换算
		}
		else
		{
			isCtrlPowOn = true; // 开机
			mcFocCtrl.Ref = MOTOR_SPEED_MAX_RPM;
		}
	}
	else
	{
		isCtrlPowOn = false; // 关机
		mcFocCtrl.Ref = 0;	 //  停止
	}
}